package example;

import org.redisson.Redisson;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.Date;

public class LockExample {

    public static final int SCAN_INTERVAL = 30000;
    public static final long LOCK_WATCH_DOG_TIMEOUT = 30000L;

    public static void main(String[] args) throws InterruptedException {
        Config config = new Config();
        config.setLockWatchdogTimeout(LOCK_WATCH_DOG_TIMEOUT);
//        config.useSingleServer()
//                .setAddress("redis://39.106.210.7:6379")
        config.useClusterServers()
                .setScanInterval(SCAN_INTERVAL)
                .addNodeAddress("redis://10.1.27.121:6379")
                .addNodeAddress("redis://10.1.27.121:6380")
                .addNodeAddress("redis://10.1.27.121:6381")
                .addNodeAddress("redis://10.1.27.122:6382")
                .addNodeAddress("redis://10.1.27.122:6383")
                .addNodeAddress("redis://10.1.27.122:6384");

        final RedissonClient redisson = Redisson.create(config);
        // 非公平可重入锁
        /*RLock lock = redisson.getLock("anyLock");
        // 获取锁
        lock.lock();
        // 尝试可超时地获取锁
        lock.tryLock(2000, 5000, TimeUnit.MILLISECONDS);
        Thread.sleep(2000);
        lock.unlock();*/

        // 公平可重入锁
        /*RLock fairLock = redisson.getFairLock("anyLock");
        fairLock.lock();
        fairLock.unlock();*/

        // 联锁
        /*RLock lock1 = redisson.getLock("lock1");
        RLock lock2 = redisson.getLock("lock2");
        RLock lock3 = redisson.getLock("lock3");
        RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
        // 同时加锁：lock1 lock2 lock3
        // 所有的锁都上锁成功才算成功。
        lock.lock();
        lock.unlock();*/

        // 红锁
        /*RLock lock1 = redisson.getLock("lock1");
        RLock lock2 = redisson.getLock("lock2");
        RLock lock3 = redisson.getLock("lock3");
        RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
        // 同时加锁：lock1 lock2 lock3
        // 红锁在大部分节点上加锁成功就算成功。
        lock.lock();
        lock.unlock();*/

        /*RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
        // 最常见的使用方法
        rwlock.readLock().lock();
        rwlock.readLock().lock();
        rwlock.readLock().unlock();
        rwlock.readLock().unlock();
        // 或
        rwlock.writeLock().lock();
        rwlock.writeLock().lock();
        rwlock.writeLock().unlock();
        rwlock.writeLock().unlock();*/


        // 信号量，最多三个人持有锁
        /*final RSemaphore semaphore = redisson.getSemaphore("semaphore");
        semaphore.trySetPermits(3);
        for (int i = 0; i < 4; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]尝试获取Semaphore锁");
                        semaphore.acquire();
                        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]成功获取到了Semaphore锁，开始工作");
                        Thread.sleep(3000);
                        semaphore.release();
                        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]释放Semaphore锁");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }).start();
        }*/

        // 闭锁(CountDownLatch)
        RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
        latch.trySetCount(3);
        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]设置了必须有3个线程执行countDown，进入等待中。。。");

        for(int i = 0; i < 3; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]在做一些操作，请耐心等待。。。。。。");
                        Thread.sleep(3000);
                        RCountDownLatch localLatch = redisson.getCountDownLatch("anyCountDownLatch");
                        localLatch.countDown();
                        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]执行countDown操作");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }).start();
        }

        latch.await();
        System.out.println(new Date() + "：线程[" + Thread.currentThread().getName() + "]收到通知，有3个线程都执行了countDown操作，可以继续往下走");
    }
}